home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / nethack.lha / nethack-3.1 / win / X11 / winmisc.c < prev    next >
C/C++ Source or Header  |  1993-01-07  |  12KB  |  476 lines

  1. /*    SCCS Id: @(#)winmisc.c    3.1    92/10/21    */
  2. /* Copyright (c) Dean Luick, 1992                  */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. /*
  6.  * Misc. popup windows: player selection and extended commands.
  7.  * 
  8.  *     + Global functions: player_selection() and get_ext_cmd().
  9.  */
  10. #include <X11/Intrinsic.h>
  11. #include <X11/StringDefs.h>
  12. #include <X11/Shell.h>
  13. #include <X11/Xaw/Command.h>
  14. #include <X11/Xaw/Form.h>
  15. #include <X11/Xaw/Label.h>
  16. #include <X11/Xaw/Cardinals.h>
  17. #include <X11/Xos.h>    /* for index() */
  18.  
  19. #include "hack.h"
  20. #include "func_tab.h"
  21. #include "winX.h"
  22.  
  23. extern const char *roles[];    /* from u_init.c */
  24.  
  25. static Widget extended_command_popup;
  26. static Widget extended_command_form;
  27. static int extended_command_selected;    /* index of the selected command; */
  28. static int ps_selected;            /* index of selected role */
  29. #define PS_RANDOM (-50)
  30. #define PS_QUIT   (-75)
  31.  
  32. static const char extended_command_translations[] =
  33.     "#override\n\
  34.      <Key>: ec_key()";
  35.  
  36. static const char player_select_translations[] =
  37.     "#override\n\
  38.      <Key>: ps_key()";
  39.  
  40.  
  41. static Widget make_menu();
  42.  
  43.  
  44. /* Player Selection -------------------------------------------------------- */
  45. /* ARGSUSED */
  46. static void
  47. ps_quit(w, client_data, call_data)
  48.     Widget w;
  49.     XtPointer client_data, call_data;
  50. {
  51.     ps_selected = PS_QUIT;
  52.     exit_x_event = TRUE;        /* leave event loop */
  53. }
  54.  
  55. /* ARGSUSED */
  56. static void
  57. ps_random(w, client_data, call_data)
  58.     Widget w;
  59.     XtPointer client_data, call_data;
  60. {
  61.     ps_selected = PS_RANDOM;
  62.     exit_x_event = TRUE;        /* leave event loop */
  63. }
  64.  
  65. /* ARGSUSED */
  66. static void
  67. ps_select(w, client_data, call_data)
  68.     Widget w;
  69.     XtPointer client_data, call_data;
  70. {
  71.     ps_selected = (int) client_data;
  72.     exit_x_event = TRUE;        /* leave event loop */
  73. }
  74.  
  75. /* ARGSUSED */
  76. void
  77. ps_key(w, event, params, num_params)
  78.     Widget w;
  79.     XEvent *event;
  80.     String *params;
  81.     Cardinal *num_params;
  82. {
  83.     char ch, *mark;
  84.  
  85.     ch = key_event_to_char((XKeyEvent *) event);
  86.     if (ch == '\0') {    /* don't accept nul char/modifier event */
  87.     /* don't beep */
  88.     return;
  89.     }
  90.     mark = index(pl_classes, highc(ch));
  91.     if (!mark) {
  92.     X11_nhbell();        /* no such class */
  93.     return;
  94.     }
  95.     ps_selected = mark - pl_classes;
  96.     exit_x_event = TRUE;
  97. }
  98.  
  99.  
  100. /* Global functions ========================================================= */
  101. void
  102. X11_player_selection()
  103. {
  104.     char buf[QBUFSZ];
  105.     char pc;
  106.     int num_roles;
  107.     Widget popup, player_form;
  108.  
  109.     if ((pc = highc(pl_character[0])) != 0) {
  110.     if (index(pl_classes, pc)) goto got_suffix;
  111.     pl_character[0] = pc = 0;
  112.     }
  113.  
  114.     for (num_roles = 0; roles[num_roles]; num_roles++)
  115.     ;    /* do nothing */
  116.  
  117.     popup = make_menu("player_selection", "Choose a Role",
  118.         player_select_translations,
  119.         "quit", ps_quit,
  120.         "random", ps_random,
  121.         num_roles, roles, ps_select, &player_form);
  122.  
  123.     ps_selected = 0;
  124.     positionpopup(popup);
  125.     nh_XtPopup(popup, XtGrabExclusive, player_form);
  126.  
  127.     /* The callbacks will enable the event loop exit. */
  128.     (void) x_event(EXIT_ON_EXIT);
  129.  
  130.     nh_XtPopdown(popup);
  131.     XtDestroyWidget(popup);
  132.  
  133.     if (ps_selected == PS_QUIT) {
  134.     clearlocks();
  135.     X11_exit_nhwindows(NULL);
  136.     terminate(0);
  137.     }
  138.  
  139.     if (ps_selected == PS_RANDOM) {
  140.     winid tmpwin;
  141.  
  142.     ps_selected = rn2(strlen(pl_classes));
  143.     pc = pl_classes[ps_selected];
  144.     Sprintf(buf, "This game you will be %s.", an(roles[ps_selected]));
  145.  
  146.     tmpwin = X11_create_nhwindow(NHW_TEXT);
  147.     X11_putstr(tmpwin, 0, "");
  148.     X11_putstr(tmpwin, 0, buf);
  149.     X11_putstr(tmpwin, 0, "");
  150.     X11_display_nhwindow(tmpwin, TRUE);
  151.     X11_destroy_nhwindow(tmpwin);
  152.  
  153.     } else if (ps_selected < 0 || ps_selected >= num_roles) {
  154.     panic("player_selection: bad select value %d\n", ps_selected);
  155.     } else {
  156.     pc = pl_classes[ps_selected];
  157.     }
  158.  
  159. got_suffix:
  160.     pl_character[0] = pc;
  161. }
  162.  
  163.  
  164. void
  165. X11_get_ext_cmd(input)
  166.     char *input;
  167. {
  168.     extended_command_selected = -1;        /* reset selected value */
  169.  
  170.     positionpopup(extended_command_popup);    /* center on cursor */
  171.     nh_XtPopup(extended_command_popup, XtGrabExclusive, extended_command_form);
  172.  
  173.     /* The callbacks will enable the event loop exit. */
  174.     (void) x_event(EXIT_ON_EXIT);
  175.  
  176.     if (extended_command_selected < 0)
  177.     *input = '\0';
  178.     else
  179.     Strcpy(input, extcmdlist[extended_command_selected].ef_txt);
  180. }
  181.  
  182. /* End global functions ===================================================== */
  183.  
  184. /* Extended Command -------------------------------------------------------- */
  185. /* ARGSUSED */
  186. static void
  187. extend_select(w, client_data, call_data)
  188.     Widget w;
  189.     XtPointer client_data, call_data;
  190. {
  191.     extended_command_selected = (int) client_data;
  192.     nh_XtPopdown(extended_command_popup);
  193.     exit_x_event = TRUE;        /* leave event loop */
  194. }
  195.  
  196. /* ARGSUSED */
  197. static void
  198. extend_dismiss(w, client_data, call_data)
  199.     Widget w;
  200.     XtPointer client_data, call_data;
  201. {
  202.     extended_command_selected = -1;    /* dismiss */
  203.     nh_XtPopdown(extended_command_popup);
  204.     exit_x_event = TRUE;        /* leave event loop */
  205. }
  206.  
  207. /* ARGSUSED */
  208. static void
  209. extend_help(w, client_data, call_data)
  210.     Widget w;
  211.     XtPointer client_data, call_data;
  212. {
  213.     /* We might need to make it known that we already have one listed. */
  214.     (void) doextlist();
  215. }
  216.  
  217. /* ARGSUSED */
  218. void
  219. ec_key(w, event, params, num_params)
  220.     Widget w;
  221.     XEvent *event;
  222.     String *params;
  223.     Cardinal *num_params;
  224. {
  225.     char ch;
  226.     int i, mark;
  227.  
  228.     ch = key_event_to_char((XKeyEvent *) event);
  229.  
  230.     if (ch == '\0') {    /* don't accept nul char/modifier event */
  231.     /* don't beep */
  232.     return;
  233.     }
  234.     if (index(quitchars, ch)) {
  235.     extended_command_selected = -1;    /* dismiss */
  236.     goto ec_key_done;
  237.     }
  238.  
  239.     /*
  240.      * Note: this depends on the fact that the help option "?" is known
  241.      * to be last and not counted.
  242.      */
  243.     for (mark = -1, i = 0; extcmdlist[i].ef_txt; i++) {
  244.     if (extcmdlist[i].ef_txt[0] == '?') continue;
  245.  
  246.     if (ch == extcmdlist[i].ef_txt[0]) {
  247.         if (mark != -1) {
  248.         X11_nhbell(); /* another command with the same first letter */
  249.         return;
  250.         }
  251.         mark = i;
  252.     }
  253.     }
  254.     if (mark == -1) {
  255.     X11_nhbell();
  256.     return;
  257.     }
  258.  
  259.     /*
  260.      * It would be nice if we could set the selected command before
  261.      * we pop the window down....  Maybe when I figure out how to do
  262.      * it.
  263.      */
  264.     extended_command_selected = mark;
  265. ec_key_done:
  266.     nh_XtPopdown(extended_command_popup);
  267.     exit_x_event = TRUE;        /* leave event loop */
  268. }
  269.  
  270. /*
  271.  * Use our own home-brewed version menu because simpleMenu is designed to
  272.  * be used from a menubox.
  273.  */
  274. void
  275. init_extended_commands_popup()
  276. {
  277.     int i, num_commands;
  278.     const char **command_list;
  279.  
  280.     /* count commands */
  281.     for (num_commands = 0; extcmdlist[num_commands].ef_txt; num_commands++)
  282.     ;    /* do nothing */
  283.  
  284.     /* If the last entry is "help", don't use it. */
  285.     if (strcmp(extcmdlist[num_commands-1].ef_txt, "?") == 0)
  286.     --num_commands;
  287.  
  288.     command_list = (const char **) alloc(num_commands * sizeof(char *));
  289.  
  290.     for (i = 0; i < num_commands; i++)
  291.     command_list[i] = extcmdlist[i].ef_txt;
  292.  
  293.     extended_command_popup = make_menu("extended_commands",
  294.                 "Extended Commands",
  295.                 extended_command_translations,
  296.                 "dismiss", extend_dismiss,
  297.                 "help", extend_help,
  298.                 num_commands, command_list, extend_select,
  299.                 &extended_command_form);
  300.  
  301.     free((char *)command_list);
  302. }
  303.  
  304. /* ------------------------------------------------------------------------- */
  305.  
  306. /*
  307.  * Create a popup widget of the following form:
  308.  * 
  309.  *              popup_label
  310.  *        ----------- ------------
  311.  *         |left_name| |right_name|
  312.  *        ----------- ------------
  313.  *        ------------------------
  314.  *        |    name1           |
  315.  *        ------------------------
  316.  *        ------------------------
  317.  *        |    name2           |
  318.  *        ------------------------
  319.  *              .
  320.  *              .
  321.  *        ------------------------
  322.  *        |    nameN           |
  323.  *        ------------------------
  324.  */
  325. static Widget
  326. make_menu(popup_name, popup_label, popup_translations,
  327.         left_name, left_callback,
  328.         right_name, right_callback,
  329.         num_names, widget_names, name_callback, formp)
  330.     char       *popup_name;
  331.     char       *popup_label;
  332.     String       popup_translations;
  333.     char       *left_name;
  334.     XtCallbackProc left_callback;
  335.     char       *right_name;
  336.     XtCallbackProc right_callback;
  337.     int           num_names;
  338.     char       **widget_names;
  339.     XtCallbackProc name_callback;
  340.     Widget       *formp;    /* return */
  341. {
  342.     Widget popup, form, label, above, left, right;
  343.     Widget *commands, *curr;
  344.     int i;
  345.     Arg args[8];
  346.     Cardinal num_args;
  347.     Dimension width, max_width;
  348.     int distance, skip;
  349.  
  350.  
  351.     commands = (Widget *) alloc(num_names * sizeof(Widget));
  352.  
  353.  
  354.     num_args = 0;
  355.     XtSetArg(args[num_args], XtNallowShellResize, True);    num_args++;
  356.  
  357.     popup = XtCreatePopupShell(popup_name,
  358.                 transientShellWidgetClass,
  359.                 toplevel, args, num_args);
  360.  
  361.     num_args = 0;
  362.     XtSetArg(args[num_args], XtNtranslations,
  363.         XtParseTranslationTable(popup_translations));    num_args++;
  364.     *formp = form = XtCreateManagedWidget("menuform",
  365.                 formWidgetClass,
  366.                 popup,
  367.                 args, num_args);
  368.  
  369.     /* Get the default distance between objects in the form widget. */
  370.     num_args = 0;
  371.     XtSetArg(args[num_args], XtNdefaultDistance, &distance);    num_args++;
  372.     XtGetValues(form, args, num_args);
  373.  
  374.     /*
  375.      * Create the label.
  376.      */
  377.     num_args = 0;
  378.     XtSetArg(args[num_args], XtNborderWidth, 0);    num_args++;
  379.     label = XtCreateManagedWidget(popup_label,
  380.                 labelWidgetClass,
  381.                 form,
  382.                 args, num_args);
  383.  
  384.     /*
  385.      * Create the left button.
  386.      */
  387.     num_args = 0;
  388.     XtSetArg(args[num_args], XtNfromVert, label);        num_args++;
  389. /*
  390.     XtSetArg(args[num_args], XtNshapeStyle,
  391.                 XmuShapeRoundedRectangle);    num_args++;
  392. */
  393.     left = XtCreateManagedWidget(left_name,
  394.             commandWidgetClass,
  395.             form,
  396.             args, num_args);
  397.     XtAddCallback(left, XtNcallback, left_callback, (XtPointer) 0);
  398.     skip = 3*distance;    /* triple the spacing */
  399.     if(!skip) skip = 3;
  400.  
  401.     /*
  402.      * Create right button.
  403.      */
  404.     num_args = 0;
  405.     XtSetArg(args[num_args], XtNfromHoriz, left);        num_args++;
  406.     XtSetArg(args[num_args], XtNfromVert, label);        num_args++;
  407. /*
  408.     XtSetArg(args[num_args], XtNshapeStyle,
  409.                 XmuShapeRoundedRectangle);    num_args++;
  410. */
  411.     right = XtCreateManagedWidget(right_name,
  412.             commandWidgetClass,
  413.             form,
  414.             args, num_args);
  415.     XtAddCallback(right, XtNcallback, right_callback, (XtPointer) 0);
  416.  
  417.  
  418.     /*
  419.      * Create and place the command widgets.
  420.      */
  421.     for (i = 0, above = left, curr = commands; i < num_names;
  422.                     i++, above = *curr, curr++) {
  423.     num_args = 0;
  424.     XtSetArg(args[num_args], XtNfromVert, above);    num_args++;
  425.     if (i == 0) {
  426.         /* if first, we are farther apart */
  427.         XtSetArg(args[num_args], XtNvertDistance, skip);    num_args++;
  428.     }
  429.  
  430.     *curr = XtCreateManagedWidget(widget_names[i],
  431.             commandWidgetClass,
  432.             form,
  433.             args, num_args);
  434.     XtAddCallback(*curr, XtNcallback, name_callback, (XtPointer) i);
  435.     }
  436.  
  437.     /*
  438.      * Now find the largest width.  Start with the width dismiss + help
  439.      * buttons, since they are adjacent.
  440.      */
  441.     XtSetArg(args[0], XtNwidth, &max_width);
  442.     XtGetValues(left, args, ONE);
  443.     XtSetArg(args[0], XtNwidth, &width);
  444.     XtGetValues(right, args, ONE);
  445.     max_width = max_width + width + distance;
  446.  
  447.     /* Next, the title. */
  448.     XtSetArg(args[0], XtNwidth, &width);
  449.     XtGetValues(label, args, ONE);
  450.     if (width > max_width) max_width = width;
  451.  
  452.     /* Finally, the commands. */
  453.     for (i = 0, curr = commands; i < num_names; i++, curr++) {
  454.     XtSetArg(args[0], XtNwidth, &width);
  455.     XtGetValues(*curr, args, ONE);
  456.     if (width > max_width) max_width = width;
  457.     }
  458.  
  459.     /*
  460.      * Finally, set all of the single line widgets to the largest width.
  461.      */
  462.     XtSetArg(args[0], XtNwidth, max_width);
  463.     XtSetValues(label, args, ONE);
  464.  
  465.     for (i = 0, curr = commands; i < num_names; i++, curr++) {
  466.     XtSetArg(args[0], XtNwidth, max_width);
  467.     XtSetValues(*curr, args, ONE);
  468.     }
  469.  
  470.     free((char *) commands);
  471.  
  472.     XtRealizeWidget(popup);
  473.  
  474.     return popup;
  475. }
  476.